// @Description 框架入口
// @Author insight21
// @Since 2021/9/11

package web

import (
	"net/http"
	"strings"
)

type HandlerFunc func(c *Context)

type Engine struct {
	router *router
	*RouterGroup
	groups []*RouterGroup // 将 Engine 作为顶层使用
}

type RouterGroup struct {
	prefix   string        // 分组名
	midWares []HandlerFunc // 中间件
	parent   *RouterGroup  // 分组嵌套
	engine   *Engine       // 全局共用一个实例
}

func New() *Engine {
	engine := &Engine{router: NewRouter()}
	engine.RouterGroup = &RouterGroup{engine: engine}
	engine.groups = []*RouterGroup{engine.RouterGroup}

	return engine
}

func (group *RouterGroup) Group(prefix string) *RouterGroup {
	engine := group.engine
	newGroup := &RouterGroup{
		prefix: prefix,
		parent: group,
		engine: engine,
	}
	engine.groups = append(engine.groups, newGroup)

	return newGroup
}

// 将中间件应用到组
func (group *RouterGroup) ApplyToGroup(midware ...HandlerFunc) {
	group.midWares = append(group.midWares, midware...)
}

func (group *RouterGroup) GET(path string, handler HandlerFunc) {
	group.addRoute("GET", path, handler)
}

func (group *RouterGroup) POST(path string, handler HandlerFunc) {
	group.addRoute("POST", path, handler)
}

func (engine *Engine) Run(addr string) (err error) {
	return http.ListenAndServe(addr, engine)
}

// 添加静态路由
func (group *RouterGroup) addRoute(method string, path string, handler HandlerFunc) {
	group.engine.router.addRoute(method, group.prefix+path, handler)
}

func (engine *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	// 通过前缀获取请求对应的中间件
	var midware []HandlerFunc

	for _, group := range engine.groups {
		if strings.HasPrefix(req.URL.Path, group.prefix) {
			midware = append(midware, group.midWares...)
		}
	}

	context := NewContext(w, req)
	context.midHandler = midware
	engine.router.handle(context)
}
